home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d18
/
pibcat.arc
/
PIBCATA.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1989-03-31
|
14KB
|
307 lines
(*----------------------------------------------------------------------*)
(* Display_Archive_Contents --- Display contents of archive file *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_Archive_Contents( ArcFileName : AnyStr );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Display_Archive_Contents *)
(* *)
(* Purpose: Displays contents of an archive (.ARC file) *)
(* *)
(* Calling sequence: *)
(* *)
(* Display_Archive_Contents( ArcFileName : AnyStr ); *)
(* *)
(* ArcFileName --- name of archive file whose contents *)
(* are to be listed. *)
(* *)
(* Calls: *)
(* *)
(* Dir_Convert_Date_And_Time *)
(* Start_Library_Listing *)
(* End_Library_Listing *)
(* Display_Page_Titles *)
(* Entry_Matches *)
(* *)
(*----------------------------------------------------------------------*)
(*----------------------------------------------------------------------*)
(* Map of Archive file entry header *)
(*----------------------------------------------------------------------*)
TYPE
FNameType = ARRAY[1..13] OF CHAR;
Archive_Entry_Type = RECORD
Marker : BYTE (* Flags beginning of entry *);
Version : BYTE (* Compression method *);
FileName : FNameType (* file and extension *);
Size : LONGINT (* Compressed size *);
Date : WORD (* Packed date *);
Time : WORD (* Packed time *);
CRC : WORD (* Cyclic Redundancy Check *);
OLength : LONGINT (* Original length *);
END;
CONST
Archive_Header_Length = 29 (* Length of an archive header entry *);
Archive_Marker = 26 (* Marks start of an archive header *);
Max_Subdirs = 20 (* Maximum number of nested subdirs *);
VAR
ArcFile : FILE (* Archive file to be read *);
Archive_Entry : Archive_Entry_Type (* Header for one file in archive *);
Archive_Pos : LONGINT (* Current byte offset in archive *);
Bytes_Read : INTEGER (* # bytes read from archive file *);
Ierr : INTEGER (* Error flag *);
(* Nested directory names in *)
(* archive *)
Subdir_Names : ARRAY[1..Max_Subdirs] OF STRING[13];
Subdir_Depth : INTEGER (* Current subdirectory in archive*);
Display_Entry : BOOLEAN (* TRUE to display this entry *);
Long_Name : AnyStr (* Long file name *);
DirS : DirStr (* Directory name *);
FExt : ExtStr (* Extension of file name *);
(*----------------------------------------------------------------------*)
(* Get_Next_Archive_Entry --- Get next header entry in archive *)
(*----------------------------------------------------------------------*)
FUNCTION Get_Next_Archive_Entry( VAR ArcEntry : Archive_Entry_Type;
VAR Display_Entry : BOOLEAN;
VAR Error : INTEGER ) : BOOLEAN;
(*----------------------------------------------------------------------*)
(* *)
(* Function: Get_Next_Archive_Entry *)
(* *)
(* Purpose: Gets header information for next file in archive *)
(* *)
(* Calling sequence: *)
(* *)
(* OK := Get_Next_Archive_Entry( VAR ArcEntry : *)
(* Archive_Entry_Type; *)
(* VAR Display_Entry : BOOLEAN; *)
(* VAR Error : INTEGER ) : *)
(* BOOLEAN; *)
(* *)
(* ArcEntry --- Header data for next file in archive *)
(* Display_Entry --- TRUE to display this entry *)
(* Error --- Error flag *)
(* OK --- TRUE if header successfully found *)
(* *)
(*----------------------------------------------------------------------*)
BEGIN (* Get_Next_Archive_Entry *)
(* Assume no error to start *)
Error := 0;
(* Assume we don't display this *)
(* entry. *)
Display_Entry := FALSE;
(* Except first time, move to *)
(* next supposed header record in *)
(* archive. *)
IF ( Archive_Pos <> 0 ) THEN
Seek( ArcFile, Archive_Pos );
(* Read in the file header entry. *)
BlockRead( ArcFile, ArcEntry, Archive_Header_Length, Bytes_Read );
Error := 0;
(* If wrong size read, or header marker *)
(* byte is incorrect, report archive *)
(* format error. *)
IF ( ( Bytes_Read < 2 ) OR
( ArcEntry.Marker <> Archive_Marker ) ) THEN
Error := Format_Error
ELSE (* Header looks ok -- figure out *)
(* whaty kind of header it is. *)
WITH ArcEntry DO
CASE Version OF
(* End of archive marker *)
0 : Error := End_Of_File;
(* Compressed file *)
1 .. 19 : BEGIN
(* Get position of next archive header *)
IF ( Bytes_Read < Archive_Header_Length ) THEN
Error := Format_Error
ELSE
BEGIN
Archive_Pos := Archive_Pos + Size +
Archive_Header_Length;
(* Adjust for older archives *)
IF ( Version = 1 ) THEN
BEGIN
OLength := Size;
Version := 2;
DEC( Archive_Pos , 2 );
END;
(* Display this entry *)
Display_Entry := TRUE;
END;
END;
30 : BEGIN (* Subdirectory begins *)
(* If there is room, add this *)
(* subdirectory to current *)
(* nesting list. *)
IF ( Bytes_Read < Archive_Header_Length ) THEN
Error := Format_Error
ELSE IF ( Subdir_Depth < Max_Subdirs ) THEN
BEGIN
INC( Subdir_Depth );
Subdir_Names[ Subdir_Depth ] :=
COPY( FileName, 1,
PRED( POS( #0 , FileName ) ) );
END
ELSE
Error := Too_Many_Subs;
Archive_Pos := Archive_Pos + Archive_Header_Length;
END;
31 : BEGIN (* End of subdirectory *)
(* Remove this subdirectory from *)
(* current nesting *)
IF ( Subdir_Depth > 0 ) THEN
DEC( Subdir_Depth );
(* Position past header *)
Archive_Pos := Archive_Pos + 2;
END;
ELSE (* Skip over other header types *)
IF ( Bytes_Read < Archive_Header_Length ) THEN
Error := Format_Error
ELSE
Archive_Pos := Archive_Pos + Size +
Archive_Header_Length;
END (* CASE *);
(* Report success/failure to calling *)
(* routine. *)
Get_Next_Archive_Entry := ( Error = 0 );
END (* Get_Next_Archive_Entry *);
(*----------------------------------------------------------------------*)
(* Display_Archive_Entry --- Display archive file entry info *)
(*----------------------------------------------------------------------*)
PROCEDURE Display_Archive_Entry( Archive_Entry : Archive_Entry_Type );
VAR
I : INTEGER;
FName : AnyStr;
TimeDate : LONGINT;
TimeDateW : ARRAY[1..2] OF WORD ABSOLUTE TimeDate;
BEGIN (* Display_Archive_Entry *)
WITH Archive_Entry DO
BEGIN
(* Pick up file name *)
FName := COPY( FileName, 1, PRED( POS( #0 , FileName ) ) );
(* See if this file matches the *)
(* entry spec wildcard. Exit if *)
(* not. *)
IF Use_Entry_Spec THEN
IF ( NOT Entry_Matches( FName ) ) THEN
EXIT;
(* Get date and time of creation *)
TimeDateW[ 1 ] := Time;
TimeDateW[ 2 ] := Date;
(* See if we're to write out *)
(* long file names. If so, *)
(* get subdirectory path *)
(* followed by file name. *)
Long_Name := '';
IF Show_Long_File_Names THEN
IF ( Subdir_Depth > 0 ) THEN
BEGIN
FOR I := 1 TO Subdir_Depth DO
Long_Name := Long_Name + Subdir_Names[ I ] + '\';
Long_Name := Long_Name + FName;
END;
(* Display info for this entry *)
Display_One_Entry( FName, Olength, TimeDate, ArcFileName,
Current_Subdirectory, Long_Name );
END;
END (* Display_Archive_Entry *);
(*----------------------------------------------------------------------*)
BEGIN (* Display_Archive_Contents *)
(* Note if LZH or LZS type. *)
FSplit( ArcFileName, DirS, Long_Name, FExt );
IF ( LENGTH( FExt ) > 1 ) THEN
IF ( FExt[ 1 ] = '.' ) THEN
DELETE( FExt, 1, 1 );
(* Open archive file and initialize *)
(* contents display. *)
IF Start_Contents_Listing( ' ' + FExt + ' file: ',
Current_Subdirectory + ArcFileName, ArcFile,
Archive_Pos, Ierr ) THEN
BEGIN
(* No subdirectories yet encountered *)
(* in archive file *)
Subdir_Depth := 0;
(* Loop over entries in archive file *)
WHILE( Get_Next_Archive_Entry( Archive_Entry , Display_Entry , Ierr ) ) DO
IF Display_Entry THEN
Display_Archive_Entry( Archive_Entry );
(* Close library files, complete display *)
End_Contents_Listing( ArcFile , Ierr );
END;
END (* Display_Archive_Contents *);